import {
  CallbackProperty,
  Cartesian2,
  Cartesian3,
  Color,
  ConstantPositionProperty,
  ConstantProperty,
  createGuid,
  CustomDataSource,
  defined,
  Entity,
  HeightReference,
  HorizontalOrigin,
  PolylineDashMaterialProperty,
  VerticalOrigin,
  Viewer,
} from "cesium";
import { MathUtils, MouseHandler } from "../CustomCesium/CustomCesium";
import MeasuringUtils from "./MeasuringUtils";
import _ from "lodash";

/**
 * description: 测量距离
 * fileName: Distance.ts
 * author: ssr
 * date: 2023-01-12 17:30:41
 * version: V1.0.0
 */
export default class MeasureDistance {
  private viewer: Viewer;
  private mouseHandlerManager: MouseHandler;
  private guid: string;
  // 实体
  private entity: Entity | null;
  // 实体id
  private entityId: string;
  // 实体标签
  private entityLabel: string;
  // 坐标点
  private positions: Cartesian3[];
  // 标识点
  private markPointsDataSource: CustomDataSource | null;

  constructor(viewer: Viewer, mouseHandlerManager: MouseHandler) {
    this.mouseHandlerManager = mouseHandlerManager;
    this.guid = createGuid();
    this.entityId = "measureDistance_" + this.guid;
    // 标识点
    this.markPointsDataSource = new CustomDataSource(
      "markPoints_" + this.entityId
    );
    this.entity = null;
    this.entityLabel = "";
    this.positions = [];
    this.viewer = this.init(viewer);
  }

  private init(viewer: Viewer) {
    if (!defined(viewer)) throw new Error("EventListener,无效的视图对象！");
    // 添加到 viewer 渲染
    this.markPointsDataSource &&
      viewer.dataSources.add(this.markPointsDataSource);
    return viewer;
  }

  /**
   * 测量
   */
  measuring() {
    if (this.mouseHandlerManager.isExists("measureLeftClick_" + this.guid)) {
      return;
    }

    if (this.entity === null) {
      this.addPolyline();
    }

    try {
      // 监听鼠标左键
      this.mouseHandlerManager.addLeftMouseClickHandler(
        "measureLeftClick_" + this.guid,
        ({ screenPosition }) => {
          // 贴地坐标or空间坐标
          const position =
            screenPosition &&
            MathUtils.getSurfaceCartesian3(this.viewer, screenPosition);

          // 无有效坐标，不能结束
          if (!position) return;
          if (!defined(position)) return;

          // 添加点
          let markPoint = this.addMeasuringPoint(position);
          this.markPointsDataSource &&
            this.markPointsDataSource.entities.add(markPoint);
          this.positions.push(position);
        }
      );

      // 鼠标移动事件回调处理
      // 移除上一个实体，添加新实体
      const throttle = _.throttle((screenPosition: Cartesian2) => {
        // 贴地坐标or空间坐标
        const position =
          screenPosition &&
          MathUtils.getSurfaceCartesian3(this.viewer, screenPosition);

        // 无有效坐标，不能结束
        if (!position) return;
        if (!defined(position)) return;

        this.positions.pop();
        this.positions.push(position);

        this.entityLabel =
          (
            MeasuringUtils.getPositionsDistance(
              MeasuringUtils.cartesianArrayToWGS84Array(
                this.viewer,
                this.positions
              )
            )
          ).toFixed(4) + "米";
        this.entity?.label &&
          (this.entity.label.text = new ConstantProperty(this.entityLabel));
        this.entity &&
          (this.entity.position = new ConstantPositionProperty(position));

        this.viewer.container.style.cursor = "pointer";
      }, 350);

      // 监听鼠标移动事件
      this.mouseHandlerManager.addMouseMoveHandler(
        "measureMouseMove_" + this.guid,
        ({ screenPosition }) => {
          // 频繁触发
          // 节流处理
          screenPosition && throttle(screenPosition);
        }
      );

      // 右键结束绘画
      this.mouseHandlerManager.addRightMouseClickHandler(
        "measureRightClick_" + this.guid,
        ({ screenPosition }) => {
          // 删除监听事件
          this.mouseHandlerManager.destroyHandlerByKey(
            "measureLeftClick_" + this.guid
          );
          this.mouseHandlerManager.destroyHandlerByKey(
            "measureMouseMove_" + this.guid
          );
          this.mouseHandlerManager.destroyHandlerByKey(
            "measureRightClick_" + this.guid
          );
          if (this.markPointsDataSource) {
            // 删除标识点
            this.markPointsDataSource.entities.removeAll();
          }
          // 删除实体
          this.viewer.entities.removeById(this.entityId);
          this.entity = null;
          this.viewer.container.style.cursor = "default";
          this.positions = [];
        }
      );
    } catch (error) {
      console.error("drawManager:", error);
    }
  }

  /**
   * 添加测量线
   */
  addPolyline() {
    const _this = this;
    const lastPosition = _.cloneDeep(_this.positions)
        .reverse()
        .find((_i, index) => index == 0),
      lastPositionClone = lastPosition?.clone();
    this.entity = new Entity({
      id: this.entityId,
      position: lastPositionClone,
      label: {
        text: _this.entityLabel,
        showBackground: true,
        font: "14px monospace",
        horizontalOrigin: HorizontalOrigin.LEFT,
        verticalOrigin: VerticalOrigin.BOTTOM,
        pixelOffset: new Cartesian2(0, 0), //left top
      },
      polyline: {
        width: 3,
        material: new PolylineDashMaterialProperty({
          color: Color.BLUE.withAlpha(0.8),
        }),
        clampToGround: true,
        positions: new CallbackProperty(function () {
          return _this.positions;
        }, false),
      },
    });
    this.viewer.entities.add(this.entity);
  }

  /**
   * 添加测量点
   */
  addMeasuringPoint(position: Cartesian3, clampToGround = true) {
    const shape = new Entity({
      position: position,
      point: {
        pixelSize: 3,
        outlineColor: Color.BLUE,
        outlineWidth: 3,
        heightReference: clampToGround
          ? HeightReference.CLAMP_TO_GROUND
          : HeightReference.NONE,
      },
      label: {
        show: this.positions.length !== 1,
        text:
          (
            MeasuringUtils.getPositionsDistance(
              MeasuringUtils.cartesianArrayToWGS84Array(
                this.viewer,
                this.positions
              )
            )
          ).toFixed(4) + "米",
        showBackground: true,
        font: "14px monospace",
        horizontalOrigin: HorizontalOrigin.LEFT,
        verticalOrigin: VerticalOrigin.BOTTOM,
        pixelOffset: new Cartesian2(-10, 30), //left top
      },
    });
    return shape;
  }

  /**
   * 清空
   */
  clearAll() {
    // 删除监听事件
    this.mouseHandlerManager.destroyHandlerByKey(
      "measureLeftClick_" + this.guid
    );
    this.mouseHandlerManager.destroyHandlerByKey(
      "measureMouseMove_" + this.guid
    );
    this.mouseHandlerManager.destroyHandlerByKey(
      "measureRightClick_" + this.guid
    );
    if (this.markPointsDataSource) {
      // 删除标识点
      this.markPointsDataSource.entities.removeAll();
      this.viewer.dataSources.remove(this.markPointsDataSource);
    }
    // 删除实体
    this.viewer.entities.removeById(this.entityId);
    this.entity = null;
    this.viewer.container.style.cursor = "default";
    this.positions = [];
  }
}
